package edu.polsl.bio.str.node.remoting;

import edu.polsl.bio.str.common.api.DotPlotService;
import edu.polsl.bio.str.common.api.NodeManagementService;
import edu.polsl.bio.str.common.exception.ServiceLocatorException;
import edu.polsl.bio.str.node.logic.NodeContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.remoting.rmi.RmiProxyFactoryBean;
import org.springframework.remoting.support.RemoteInvocationFactory;

/**
 * //todo class description
 * <p/>
 * Created on: Jun 12, 2011 8:58:53 PM <br/>
 * <a href="http://www.polsl.pl">www.polsl.pl</a>
 *
 * @author lukasz.olczak@polsl.pl
 */
public class RmiServiceLocator implements ServiceLocator {
  /**
   * slf4j Logger.
   */
  private static final Logger log = LoggerFactory.getLogger(RmiServiceLocator.class.getName());

  private static final String SERVICE_NAME_PREFIX = "str";

  private NodeContext nodeContext;

  /**
   * Remote invocation factory.
   */
  private RemoteInvocationFactory remoteInvocationFactory;

  /**
   * Lookups service.
   *
   * @param name             - service name
   * @param serviceInterface - service interface
   * @return - service
   * @throws ServiceLocatorException - throws exception if something goes wrong
   */
  public final Object lookupService(String name, Class serviceInterface) throws ServiceLocatorException {
    log.debug("Looking up service={} on RMI address={}", name, getRmiUrl());
    try {
      RmiProxyFactoryBean rmiProxyFactoryBean = new RmiProxyFactoryBean();
      rmiProxyFactoryBean.setServiceUrl(getRemoteUrl(name));
      rmiProxyFactoryBean.setServiceInterface(serviceInterface);
      rmiProxyFactoryBean.afterPropertiesSet();
      rmiProxyFactoryBean.setRemoteInvocationFactory(remoteInvocationFactory);
      return rmiProxyFactoryBean.getObject();
    } catch (Exception e) {
      throw new ServiceLocatorException("Problems with locating service=" + name + ", class=" + serviceInterface, e);
    }
  }

  private String getRemoteUrl(String serviceName) {
    String remoteUrl = getRmiUrl() + getServiceName(serviceName);
    return remoteUrl;
  }

  private String getRmiUrl() {
    return "rmi://" + nodeContext.getManagerIp() + ":1199/";
  }

  /**
   * Returns service name with prefix.
   *
   * @param serviceName - service name
   * @return - service name with prefix
   */
  private String getServiceName(String serviceName) {
    return SERVICE_NAME_PREFIX + "/" + serviceName;
  }

  @Override
  public DotPlotService getDotPlotService() throws ServiceLocatorException {
    return (DotPlotService) lookupService("DotPlotService", DotPlotService.class);
  }

  @Override
  public NodeManagementService getNodeManagementService() throws ServiceLocatorException {
    return (NodeManagementService) lookupService("NodeManagementService", NodeManagementService.class);
  }

  public void setNodeContext(NodeContext nodeContext) {
    this.nodeContext = nodeContext;
  }

  public void setRemoteInvocationFactory(RemoteInvocationFactory remoteInvocationFactory) {
    this.remoteInvocationFactory = remoteInvocationFactory;
  }
}
